/**
 * File: BucketNodeIdWriterProcessor.java
 * Created by: mhaimel
 * Created on: May 21, 2010
 * CVS:  $Id: BucketNodeIdWriterProcessor.java 1.0 May 21, 2010 2:29:08 PM mhaimel Exp $
 */
package uk.ac.ebi.curtain.processor.general;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;

import uk.ac.ebi.curtain.model.graph.Node;
import uk.ac.ebi.curtain.model.graph.curtain.ContigInfo;
import uk.ac.ebi.curtain.model.graph.curtain.CurtainGraph;
import uk.ac.ebi.curtain.model.graph.curtain.ReadWrapper;
import uk.ac.ebi.curtain.processor.AbstractQueueProcessor;
import uk.ac.ebi.curtain.util.FileHelper;
import uk.ac.ebi.curtain.utils.CurtainUncheckedException;
import uk.ac.ebi.curtain.utils.StatisticHelper;
import uk.ac.ebi.velvet.model.Supercontig;

/**
 * @author mhaimel
 *
 */
public class BucketReadInfoProcessor extends AbstractQueueProcessor<File, File> {

	@Override
	protected File buildReturnObject() {
		return null;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	protected File doProcess(File bucketDir) {
		if(null == getContext().getGraph()){
			throw new CurtainUncheckedException("Graph in not loaded - required!!!");
		}
		
		Integer bucketId = FileHelper.getIdFromSubDirectory(bucketDir);
		
		//get file
		File sumFile = Supercontig.getNodeIdOutputFile(bucketDir);
		if(!sumFile.exists()){
			throw new CurtainUncheckedException("File does not exist: " + sumFile);
		}
		
		// Load lines in file
		List<String> lines = Collections.emptyList();
		try {
			lines = FileUtils.readLines(sumFile);
		} catch (IOException e) {
			throw new CurtainUncheckedException("Problems reading file " + sumFile);
		}
		
		// Translate Strings into ids
		Set<Long> nodeIds = new HashSet<Long>();
		for(String l : lines){
			l = l.trim();
			if(StringUtils.isNotBlank(l)){
				Long val = Long.valueOf(l);
				nodeIds.add(val);
			}
		}
		
		CurtainGraph cgraph = getContext().getGraph();
		Integer cat = cgraph.getCategories();
		
		long ctgBpCnt = 0l;
		long[] cngBpTotal = new long[cat];
		long[] wCov = new long[cat];
		long[] readBpTotal = new long[cat];
		long[] readCntTotal = new long[cat];
		ArrayList<Double>[] covArr = new ArrayList[cat];
		for(int i = 0; i < cat; ++i){
			covArr[i] = new ArrayList<Double>();
			cngBpTotal[i] = 0l;
			readBpTotal[i] = 0l;
			readCntTotal[i] = 0l;
			wCov[i] = 0l;
		}
		
		List<Long> nodeList = new ArrayList<Long>(nodeIds);
		int length = nodeList.size();
		for(int i = 0; i < length; ++i){
			long nid = nodeList.get(i);
			Node<ContigInfo, ReadWrapper> node = cgraph.getNode(nid);
			ContigInfo value = node.getValue();
			ctgBpCnt += value.getLength();
			Long len = value.getLength();
			for(int j = 0; j < cat; ++j){
				double bpCoverage = value.getCoverageBpCount(j);
				readBpTotal[j] += (long) bpCoverage;
				cngBpTotal[j] += len;
				readCntTotal[j] += value.getCoverageSequCount(j);
				readCntTotal[j] += value.getFull(j);
				double bpCov = value.calculateSequenceCoverage(j);
				wCov[j] += bpCov*len;
				covArr[j].add(bpCov);
			}
		}
		BucketReadInfo[] arr = new BucketReadInfo[cat];
		for(int j = 0; j < cat; ++j){
			File f = Supercontig.getCategoryInfoFile(bucketDir, j);
			long cnt = readCntTotal[j];
			BucketReadInfo info = new BucketReadInfo((long)bucketId, j);
			Double rlen = 0d;
			if(cnt > 0){
				rlen = Double.valueOf(readBpTotal[j])/cnt;
			} 
			info.setAvgReadLength(rlen.intValue());
			info.setBpReads(readBpTotal[j]);
			info.setBpContigs(ctgBpCnt);
			info.setNumberOfReads(readCntTotal[j]);
			arr[j] = info;
			ArrayList<Double> arrList =covArr[j];
			Collections.sort(arrList);
			
			StatisticHelper<Double> helper = new StatisticHelper<Double>(arrList);
			
			Double median = helper.median();
//			Number mean = helper.mean();
			double wmean = ((double)wCov[j])/cngBpTotal[j];
			info.setMedianBpCoverage(median);
			info.setWeightedMeanCoverage(wmean);
			info.toFile(f, false);
			
//			info.calculateBpCoverage();
//			info.calculateKmerCoverage(63);
//			info.calculateKmerCoverage(55);
//			info.calculateKmerCoverage(31);			
			
		}		
		return bucketDir;
	}
	
}







